package com.plum.admin.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.plum.admin.common.exception.BaseException;
import com.plum.admin.common.strategy.data.DataScopeContext;
import com.plum.admin.modules.sys.dto.RoleDTO;
import com.plum.admin.modules.sys.dto.RoleMenuDTO;
import com.plum.admin.modules.sys.entity.SysRole;
import com.plum.admin.modules.sys.entity.SysRoleDept;
import com.plum.admin.modules.sys.entity.SysRoleMenu;
import com.plum.admin.modules.sys.mapper.SysRoleMapper;
import com.plum.admin.modules.sys.service.ISysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色表 服务实现类
 * </p>
 *
 * @author 子丶沫
 * @since 2021-08-13
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    private final DataScopeContext dataScopeContext;
    @Override
    public List<SysRole> findRoleByUserId(String userId) {
        return baseMapper.findRoleByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveRolePermission(RoleMenuDTO roleMenuDTO) {
        String roleId = roleMenuDTO.getRoleId();
        int i = baseMapper.deleteByRoleId(roleId);
        List<SysRoleMenu> roleMenuList = roleMenuDTO.getPermissionIds().stream()
                .map(menuId -> {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setRoleId(roleId);
                    roleMenu.setMenuId(menuId);
                    return roleMenu;
                }).collect(Collectors.toList());
        baseMapper.batchSaveRoleMenu(roleMenuList);
        return i>0;
    }

    @Override
    public IPage<SysRole> findRoleList(Page<SysRole> page,SysRole role) {
        Page<SysRole> rolePage = baseMapper.selectPage(page, Wrappers.<SysRole>query()
                .lambda()
                .like(StrUtil.isNotBlank(role.getRoleName()), SysRole::getRoleName, role.getRoleName()));
        List<SysRole> roleList = rolePage.getRecords().stream().peek(sysRole -> {
            sysRole.setRoleDeptIdList(baseMapper.findDeptIdByRoleId(sysRole.getId()));
            sysRole.setMenuIdList(baseMapper.findMenuIdListByRoleId(sysRole.getId()));
        }).collect(Collectors.toList());
        rolePage.setRecords(roleList);
        return rolePage;
    }

    /**
     * 保存角色
     * @param roleDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertRole(RoleDTO roleDTO) {
        SysRole role=new SysRole();
        BeanUtil.copyProperties(roleDTO,role);
        List<String> deptIds = dataScopeContext.getDeptIdListForDataScope(roleDTO, roleDTO.getDsType());
        StringJoiner joiner = new StringJoiner(",");
        deptIds.forEach(joiner::add);
        role.setDsScope(joiner.toString());
        int count=baseMapper.insert(role);
        saveRoleDept(role,deptIds);
        return count>0;
    }

    /**
     * 修改角色
     * @param roleDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRole(RoleDTO roleDTO) {
        SysRole sysRole=SysRole.builder().build();
        BeanUtil.copyProperties(roleDTO,sysRole);
        List<String> deptIds = dataScopeContext.getDeptIdListForDataScope(roleDTO, roleDTO.getDsType());
        StringJoiner joiner = new StringJoiner(",");
        deptIds.forEach(joiner::add);
        sysRole.setDsScope(joiner.toString());
        int count=baseMapper.updateById(sysRole);
        baseMapper.deleteDeptByRoleId(sysRole.getId());
        saveRoleDept(sysRole,deptIds);
        return count>0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRole(List<String> roleIdList) {
        List<String> list = baseMapper.findUserIdByRoleId(roleIdList);
        if(CollUtil.isNotEmpty(list)){
            throw new BaseException("角色下已存在用户,无法删除");
        }
        for (String roleId : roleIdList) {
            baseMapper.deleteByRoleId(roleId);
            baseMapper.deleteDeptByRoleId(roleId);
        }
        int count = baseMapper.deleteBatchIds(roleIdList);
        return count>0;
    }

    private void saveRoleDept(SysRole role, List<String> deptIds) {
        if(CollUtil.isNotEmpty(deptIds)){
            List<SysRoleDept> roleDeptList = deptIds.stream()
                    .map(deptId -> {
                        SysRoleDept roleDept=new SysRoleDept();
                        roleDept.setRoleId(role.getId());
                        roleDept.setDeptId(deptId);
                        return roleDept;
                    }).collect(Collectors.toList());
            baseMapper.batchSaveRoleDept(roleDeptList);
        }
    }
}
